package task

import com.aliyun.fc.runtime.Context
import com.aliyun.fc.runtime.StreamRequestHandler
import form.ExchangeForm
import form.LoginForm
import main.Gf2BbsRetrofit
import main.LoginRetrofit
import org.slf4j.LoggerFactory
import response.base.Res
import response.topic.TopicInfo
import java.io.InputStream
import java.io.OutputStream
import java.math.BigInteger
import java.security.MessageDigest

/**
 * @author BX-Gin
 * @since 2024/6/6 上午11:11
 */
class BbsTaskHandler : StreamRequestHandler {
    private lateinit var retrofit: Gf2BbsRetrofit
    private val logger = LoggerFactory.getLogger(this::class.java)

    override fun handleRequest(p0: InputStream?, p1: OutputStream?, p2: Context?) {
        val line = "-".repeat(10)
        logger.info("{}{}{}", line, "获取令牌", line)
        try {
            val auth = obtainAuthorization()
            if (auth == null) {
                logger.error("{}{}{}", line, "令牌获取失败，放弃任务", line)
                return
            }
            retrofit = Gf2BbsRetrofit(auth)
        } catch (e: Exception) {
            logger.error("{}{}{}", line, "发生异常，令牌获取失败，放弃任务", line)
            e.printStackTrace()
            return
        }

        logger.info("{}{}{}", line, "签到", line)
        signIn()
        logger.info("{}{}{}", line, "日常", line)
        daily()
        logger.info("{}{}{}", line, "道具", line)
        exchange()
    }

    private fun obtainAuthorization(): String? {
        //从环境变量中获取参数
        val authorization = getValue("Authorization", "auth")
        // 用户名：手机或邮箱
        val username = getValue("Username", "username", "user")
        val password = getValue("Password", "password", "pwd", "passwd")
        // 如果用户名或密码为空 直接返回 authorization
        if (username == null || password == null) return authorization
        // 发送请求获取token
        return LoginRetrofit().accountApi.login(LoginForm(username, md5Pwd(password))).execute().body()?.data?.account?.token
    }


    /**
     * 签到
     */
    private fun signIn() {
        logger.info("开始签到")
        val res = retrofit.taskApi.postSignIn().execute().body()
        printResult("签到", "", res)
    }

    /**
     * 日常任务
     */
    private fun daily() {
        val api = retrofit.topicApi
        logger.info("查询主题列表")

        val topicList = api.getList().execute().body()?.data?.list

        if (topicList.isNullOrEmpty()) {
            logger.warn("查询主题列表失败")
            return
        }
        // 分享
        share(topicList[0])

        // 筛选未点赞过的主题，进行浏览和点赞
        topicList.filter { it.liked == false }.subList(0, 3).forEach { browse(it); like(it) }

        logger.info("任务结束")
    }

    /**
     * 兑换道具
     */
    private fun exchange() {
        val api = retrofit.itemApi
        logger.info("查询道具")
        val items = api.getExchangeList().execute().body()?.data?.list
        if (items.isNullOrEmpty()) {
            logger.warn("道具查询失败")
            return
        }
        val list = items.filter { it.exchangeCount!! < it.maxExchangeCount!! }
        if (list.isEmpty()) {
            logger.info("道具已全部兑换,任务结束")
            return
        }
        list.forEach {
            // 剩余数量决定循环次数
            for (i in it.exchangeCount!! until it.maxExchangeCount!!) {
                val info = "id = ${it.exchangeId}, name = ${it.itemName}"
                logger.info("兑换道具: {}", info)
                val res = api.postExchange(ExchangeForm(it.exchangeId!!)).execute().body()
                printResult("兑换", info, res)
            }
        }
        logger.info("任务结束")
    }


    /**
     * 分享主题
     * @param topicInfo TopicInfo
     */
    private fun share(topicInfo: TopicInfo) {
        val id = topicInfo.topicId ?: return
        val title = topicInfo.title ?: return
        val info = "id = $id, title = $title"
        logger.info("分享主题: {}", info)
        val res = retrofit.topicApi.getShare(id).execute().body()
        printResult("分享", info, res)
    }

    /**
     * 浏览主题
     * @param topicInfo TopicInfo
     */
    private fun browse(topicInfo: TopicInfo) {
        val id = topicInfo.topicId ?: return
        val title = topicInfo.title ?: return
        val info = "id = $id, title = $title"
        logger.info("浏览主题: {}", info)
        val res = retrofit.topicApi.getTopic(id).execute().body()
        printResult("浏览", info, res)
    }

    /**
     * 点赞主题
     * @param topicInfo TopicInfo
     */
    private fun like(topicInfo: TopicInfo) {
        val id = topicInfo.topicId ?: return
        val title = topicInfo.title ?: return
        val info = "id = $id, title = $title"
        logger.info("点赞主题: {}", info)
        val res = retrofit.topicApi.getLike(id).execute().body()


        printResult("点赞", info, res)
    }

    private fun printResult(action: String, suffix: String, res: Res<*>?) {
        if (res == null) {
            logger.warn("{}错误, {}", action, suffix)
            return
        }
        if (res.code == 0) {
            logger.info("{}成功, {}, {}", action, res.message, suffix)
        } else {
            logger.info("{}失败, {}, {}", action, res.message, suffix)
        }
    }

    companion object {
        /**
         * 按顺序获取第一个非空环境变量
         * @param keys Array<out String>
         * @return String?
         */
        fun getValue(vararg keys: String): String? = keys.map { System.getenv(it)?.trim() }.firstOrNull { it?.isNotEmpty() == true }

        /**
         * 对密码使用md5加密
         * @param password 明文密码
         * @return String!
         */
        fun md5Pwd(password: String) = MessageDigest.getInstance("md5").digest(password.toByteArray()).let { BigInteger(1, it).toString(16) }
    }
}